from typing import Dict, List, Any, Optional
from fastapi import APIRouter, Depends, HTTPException, status, Path, Query
from sqlalchemy import select, or_, and_, text
from sqlalchemy.ext.asyncio import AsyncSession
from datetime import datetime

from app.models.db import User, DataSet, Role, RoleDatasetAccess, UserRole,get_async_session
from app.models.user import current_active_user


router = APIRouter(
    prefix="/role-datasets",
    tags=["角色数据集权限"],
    responses={404: {"description": "未找到"}},
)

# =============== 授权接口 ===============

@router.post("/grant", response_model=Dict[str, Any])
async def grant_dataset_access(
    access_data: Dict[str, Any],
    current_user: User = Depends(current_active_user),
    session: AsyncSession = Depends(get_async_session)
):
    """授予角色数据集访问权限
    
    Args:
        access_data: 包含授权信息的数据
            - role_id: 角色ID
            - dataset_id: 数据集ID
            - can_export: 是否可以导出数据（可选）
            - expires_at: 过期时间（可选）
    """
    try:
        # 验证当前用户是否有管理权限
        if not current_user.is_superuser:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="只有超级管理员可以管理访问权限"
            )
        
        # 验证角色是否存在
        result = await session.execute(
            select(Role).filter(Role.id == access_data.get("role_id"))
        )
        role = result.scalar_one_or_none()
        
        if not role:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"角色不存在: {access_data.get('role_id')}"
            )
        
        # 验证数据集是否存在
        result = await session.execute(
            select(DataSet).filter(DataSet.id == access_data.get("dataset_id"))
        )
        dataset = result.scalar_one_or_none()
        
        if not dataset:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"数据集不存在: {access_data.get('dataset_id')}"
            )
        
        # 检查是否已存在访问权限
        result = await session.execute(
            select(RoleDatasetAccess).filter(
                RoleDatasetAccess.role_id == access_data.get("role_id"),
                RoleDatasetAccess.dataset_id == access_data.get("dataset_id")
            )
        )
        existing_access = result.scalar_one_or_none()
        
        if existing_access:
            # 更新现有权限
            existing_access.can_export = access_data.get("can_export", False)
            existing_access.updated_at = datetime.now()
            
            if "expires_at" in access_data and access_data["expires_at"]:
                expires_at = datetime.fromisoformat(access_data["expires_at"].replace("Z", "+00:00"))
                existing_access.expires_at = expires_at
            
            await session.commit()
            await session.refresh(existing_access)
            
            return {
                "success": True,
                "message": "角色数据集访问权限已更新",
                "data": existing_access.dict()
            }
        else:
            # 创建新的访问权限
            new_access = RoleDatasetAccess(
                role_id=access_data.get("role_id"),
                dataset_id=access_data.get("dataset_id"),
                can_export=access_data.get("can_export", False)
            )
            
            if "expires_at" in access_data and access_data["expires_at"]:
                expires_at = datetime.fromisoformat(access_data["expires_at"].replace("Z", "+00:00"))
                new_access.expires_at = expires_at
            
            session.add(new_access)
            await session.commit()
            await session.refresh(new_access)
            
            return {
                "success": True,
                "message": "角色数据集访问权限已授予",
                "data": new_access.dict()
            }
    
    except HTTPException:
        raise
    
    except Exception as e:
        await session.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"授予角色数据集访问权限失败: {str(e)}"
        )


@router.delete("/{access_id}", response_model=Dict[str, Any])
async def revoke_dataset_access(
    access_id: str = Path(..., title="访问权限ID"),
    current_user: User = Depends(current_active_user),
    session: AsyncSession = Depends(get_async_session)
):
    """撤销角色数据集访问权限
    
    Args:
        access_id: 访问权限ID
    """
    try:
        # 查询访问权限
        result = await session.execute(
            select(RoleDatasetAccess).filter(RoleDatasetAccess.id == access_id)
        )
        access = result.scalar_one_or_none()
        
        if not access:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"访问权限不存在: {access_id}"
            )
        
        # 验证当前用户是否有权限撤销 (只有超级管理员可以撤销)
        if not current_user.is_superuser:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="只有超级管理员可以撤销访问权限"
            )
        
        # 使用SQL执行删除，而不是直接删除对象
        await session.execute(
            text("DELETE FROM dk_role_dataset_access WHERE id = :access_id"),
            {"access_id": access_id}
        )
        await session.commit()
        
        return {
            "success": True,
            "message": "角色数据集访问权限已撤销"
        }
    
    except HTTPException:
        raise
    
    except Exception as e:
        await session.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"撤销角色数据集访问权限失败: {str(e)}"
        )


@router.post("/batch-grant", response_model=Dict[str, Any])
async def batch_grant_dataset_access(
    batch_data: Dict[str, Any],
    current_user: User = Depends(current_active_user),
    session: AsyncSession = Depends(get_async_session)
):
    """批量授予角色数据集访问权限
    
    Args:
        batch_data: 包含批量授权信息的数据
            - role_ids: 角色ID列表
            - dataset_ids: 数据集ID列表
            - can_export: 是否可以导出数据（可选）
            - expires_at: 过期时间（可选）
    """
    try:
        # 仅超级管理员可以批量授权
        if not current_user.is_superuser:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="只有超级管理员可以管理访问权限"
            )
        
        role_ids = batch_data.get("role_ids", [])
        dataset_ids = batch_data.get("dataset_ids", [])
        can_export = batch_data.get("can_export", False)
        expires_at = None
        
        if not role_ids or not dataset_ids:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="角色IDs和数据集IDs不能为空"
            )
        
        if "expires_at" in batch_data and batch_data["expires_at"]:
            expires_at = datetime.fromisoformat(batch_data["expires_at"].replace("Z", "+00:00"))
        
        # 验证所有角色是否存在
        role_result = await session.execute(
            select(Role).filter(Role.id.in_(role_ids))
        )
        roles = role_result.scalars().all()
        found_role_ids = [role.id for role in roles]
        
        missing_role_ids = [rid for rid in role_ids if rid not in found_role_ids]
        if missing_role_ids:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"以下角色不存在: {', '.join(missing_role_ids)}"
            )
        
        # 验证所有数据集是否存在
        dataset_result = await session.execute(
            select(DataSet).filter(DataSet.id.in_(dataset_ids))
        )
        datasets = dataset_result.scalars().all()
        found_dataset_ids = [dataset.id for dataset in datasets]
        
        missing_dataset_ids = [dsid for dsid in dataset_ids if dsid not in found_dataset_ids]
        if missing_dataset_ids:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"以下数据集不存在: {', '.join(missing_dataset_ids)}"
            )
        
        # 批量授权处理
        granted_count = 0
        failed_count = 0
        
        for role_id in role_ids:
            for dataset_id in dataset_ids:
                try:
                    # 检查是否已存在访问权限
                    result = await session.execute(
                        select(RoleDatasetAccess).filter(
                            RoleDatasetAccess.role_id == role_id,
                            RoleDatasetAccess.dataset_id == dataset_id
                        )
                    )
                    existing_access = result.scalar_one_or_none()
                    
                    if existing_access:
                        # 更新现有权限
                        existing_access.can_export = can_export
                        existing_access.updated_at = datetime.now()
                        existing_access.expires_at = expires_at
                    else:
                        # 创建新的访问权限
                        new_access = RoleDatasetAccess(
                            role_id=role_id,
                            dataset_id=dataset_id,
                            can_export=can_export,
                            expires_at=expires_at
                        )
                        session.add(new_access)
                    
                    granted_count += 1
                except Exception:
                    failed_count += 1
        
        # 提交事务
        await session.commit()
        
        return {
            "success": True,
            "message": "批量授权处理完成",
            "data": {
                "granted_count": granted_count,
                "failed_count": failed_count,
                "total_count": len(role_ids) * len(dataset_ids)
            }
        }
    
    except HTTPException:
        raise
    
    except Exception as e:
        await session.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"批量授权失败: {str(e)}"
        )


@router.post("/batch-revoke", response_model=Dict[str, Any])
async def batch_revoke_dataset_access(
    batch_data: Dict[str, Any],
    current_user: User = Depends(current_active_user),
    session: AsyncSession = Depends(get_async_session)
):
    """批量撤销角色数据集访问权限
    
    Args:
        batch_data: 包含批量撤销授权信息的数据
            - role_ids: 角色ID列表
            - dataset_ids: 数据集ID列表
    """
    try:
        # 仅超级管理员可以批量撤销授权
        if not current_user.is_superuser:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="只有超级管理员可以管理访问权限"
            )
        
        role_ids = batch_data.get("role_ids", [])
        dataset_ids = batch_data.get("dataset_ids", [])
        
        if not role_ids or not dataset_ids:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="角色IDs和数据集IDs不能为空"
            )
        
        # 查询匹配的访问权限记录，只获取ID
        query = select(RoleDatasetAccess.id).filter(
            RoleDatasetAccess.role_id.in_(role_ids),
            RoleDatasetAccess.dataset_id.in_(dataset_ids)
        )
        
        result = await session.execute(query)
        access_ids = [row[0] for row in result.all()]
        
        # 记录删除数量
        revoked_count = len(access_ids)
        
        if access_ids:
            # 使用SQL执行批量删除，避免ORM关系问题
            sql = text("DELETE FROM dk_role_dataset_access WHERE id IN :access_ids")
            params = {"access_ids": tuple(access_ids) if len(access_ids) > 1 else (access_ids[0],)}
            await session.execute(sql, params)
        
        # 提交事务
        await session.commit()
        
        return {
            "success": True,
            "message": "批量撤销授权处理完成",
            "data": {
                "revoked_count": revoked_count,
                "total_possible": len(role_ids) * len(dataset_ids)
            }
        }
    
    except HTTPException:
        raise
    
    except Exception as e:
        await session.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"批量撤销授权失败: {str(e)}"
        )


# =============== 查询接口 ===============

@router.get("/by-role/{role_id}", response_model=Dict[str, Any])
async def get_role_datasets(
    role_id: str = Path(..., title="角色ID"),
    current_user: User = Depends(current_active_user),
    session: AsyncSession = Depends(get_async_session)
):
    """获取角色有权限访问的数据集列表
    
    Args:
        role_id: 角色ID
    """
    try:
        # 仅超级管理员可以查看角色权限
        if not current_user.is_superuser:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="只有超级管理员可以查看角色的数据集访问权限"
            )
        
        # 验证角色是否存在
        result = await session.execute(
            select(Role).filter(Role.id == role_id)
        )
        role = result.scalar_one_or_none()
        
        if not role:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"角色不存在: {role_id}"
            )
        
        # 构建查询 - 使用显式JOIN
        query = (
            select(RoleDatasetAccess, DataSet)
            .join(DataSet, RoleDatasetAccess.dataset_id == DataSet.id)
            .filter(RoleDatasetAccess.role_id == role_id)
        )
        
        # 执行查询
        result = await session.execute(query)
        role_datasets = result.all()
        
        # 构建响应数据
        datasets_with_access = []
        for access, dataset in role_datasets:
            # 检查权限是否已过期
            if access.expires_at and access.expires_at < datetime.now():
                continue
                
            dataset_data = dataset.to_dict()
            dataset_data["access"] = access.dict()
            datasets_with_access.append(dataset_data)
        
        return {
            "success": True,
            "data": datasets_with_access
        }
    
    except HTTPException:
        raise
    
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取角色数据集列表失败: {str(e)}"
        )


@router.get("/by-dataset/{dataset_id}", response_model=Dict[str, Any])
async def get_dataset_roles(
    dataset_id: str = Path(..., title="数据集ID"),
    current_user: User = Depends(current_active_user),
    session: AsyncSession = Depends(get_async_session)
):
    """获取有权限访问特定数据集的角色列表
    
    Args:
        dataset_id: 数据集ID
    """
    try:
        # 验证数据集是否存在
        result = await session.execute(
            select(DataSet).filter(DataSet.id == dataset_id)
        )
        dataset = result.scalar_one_or_none()
        
        if not dataset:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"数据集不存在: {dataset_id}"
            )
        
        # 验证当前用户是否有权限查看 - 仅超级管理员可以查看
        if not current_user.is_superuser:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="只有超级管理员可以查看数据集的角色访问权限"
            )
        
        # 查询所有有权限访问的角色 - 使用显式JOIN
        query = (
            select(RoleDatasetAccess, Role)
            .join(Role, RoleDatasetAccess.role_id == Role.id)
            .filter(RoleDatasetAccess.dataset_id == dataset_id)
        )
        
        result = await session.execute(query)
        dataset_roles = result.all()
        
        # 构建响应数据
        roles_with_access = []
        for access, role in dataset_roles:
            # 检查权限是否已过期
            if access.expires_at and access.expires_at < datetime.now():
                continue
                
            role_data = role.dict()
            role_data["access"] = access.dict()
            roles_with_access.append(role_data)
        
        return {
            "success": True,
            "data": roles_with_access
        }
    
    except HTTPException:
        raise
    
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取数据集角色列表失败: {str(e)}"
        )


@router.get("/by-user/{user_id}", response_model=Dict[str, Any])
async def get_user_datasets_by_roles(
    user_id: str = Path(..., title="用户ID"),
    current_user: User = Depends(current_active_user),
    session: AsyncSession = Depends(get_async_session)
):
    """获取用户通过角色权限可以访问的数据集列表
    
    Args:
        user_id: 用户ID
    """
    try:
        # 仅超级管理员或用户自己可以查看
        if not current_user.is_superuser and str(current_user.id) != user_id:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="您没有权限查看其他用户的数据集访问权限"
            )
        
        # 验证用户是否存在
        result = await session.execute(
            select(User).filter(User.id == user_id)
        )
        user = result.scalar_one_or_none()
        
        if not user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"用户不存在: {user_id}"
            )
        
        # 获取用户的所有角色
        user_roles_result = await session.execute(
            select(UserRole).filter(UserRole.user_id == user_id)
        )
        user_roles = user_roles_result.scalars().all()
        role_ids = [ur.role_id for ur in user_roles]
        
        if not role_ids:
            return {
                "success": True,
                "data": [],
                "message": "用户未分配任何角色"
            }
        
        # 获取用户通过角色可以访问的所有数据集
        query = (
            select(RoleDatasetAccess, DataSet, Role)
            .join(DataSet, RoleDatasetAccess.dataset_id == DataSet.id)
            .join(Role, RoleDatasetAccess.role_id == Role.id)
            .filter(RoleDatasetAccess.role_id.in_(role_ids))
        )
        
        result = await session.execute(query)
        role_datasets = result.all()
        
        # 构建响应数据，按数据集分组（如果多个角色可以访问同一数据集）
        datasets_map = {}
        
        for access, dataset, role in role_datasets:
            # 检查权限是否已过期
            if access.expires_at and access.expires_at < datetime.now():
                continue
            
            dataset_id = dataset.id
            
            if dataset_id not in datasets_map:
                dataset_data = dataset.to_dict()
                dataset_data["roles"] = []
                dataset_data["can_export"] = access.can_export
                datasets_map[dataset_id] = dataset_data
            else:
                # 如果任何一个角色允许导出，则用户可以导出
                if access.can_export:
                    datasets_map[dataset_id]["can_export"] = True
            
            # 添加提供权限的角色信息
            role_info = {
                "role_id": role.id,
                "role_name": role.name,
                "can_export": access.can_export,
                "expires_at": access.expires_at.isoformat() if access.expires_at else None
            }
            
            datasets_map[dataset_id]["roles"].append(role_info)
        
        return {
            "success": True,
            "data": list(datasets_map.values())
        }
    
    except HTTPException:
        raise
    
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取用户数据集列表失败: {str(e)}"
        )


@router.get("/check-access", response_model=Dict[str, Any])
async def check_dataset_access(
    user_id: str = Query(..., description="用户ID"),
    dataset_id: str = Query(..., description="数据集ID"),
    current_user: User = Depends(current_active_user),
    session: AsyncSession = Depends(get_async_session)
):
    """检查用户是否有权限访问特定数据集（通过角色）
    
    Args:
        user_id: 用户ID
        dataset_id: 数据集ID
    """
    try:
        # 如果是超级管理员，直接返回有权限
        if current_user.is_superuser:
            return {
                "success": True,
                "data": {
                    "has_access": True,
                    "can_export": True
                }
            }
        
        # 获取用户的所有角色
        user_roles_result = await session.execute(
            select(UserRole).filter(UserRole.user_id == user_id)
        )
        user_roles = user_roles_result.scalars().all()
        role_ids = [ur.role_id for ur in user_roles]
        
        if not role_ids:
            return {
                "success": True,
                "data": {
                    "has_access": False
                }
            }
        
        # 检查用户的任何角色是否有权限访问该数据集
        access_result = await session.execute(
            select(RoleDatasetAccess).filter(
                RoleDatasetAccess.role_id.in_(role_ids),
                RoleDatasetAccess.dataset_id == dataset_id
            )
        )
        accesses = access_result.scalars().all()
        
        if not accesses:
            return {
                "success": True,
                "data": {
                    "has_access": False
                }
            }
        
        # 检查是否有任何一个未过期的访问权限
        valid_accesses = []
        for access in accesses:
            if not access.expires_at or access.expires_at >= datetime.now():
                valid_accesses.append(access)
        
        if not valid_accesses:
            return {
                "success": True,
                "data": {
                    "has_access": False,
                    "expired": True
                }
            }
        
        # 如果有任何一个角色允许导出，则用户可以导出
        can_export = any(access.can_export for access in valid_accesses)
        # 找出最晚的过期时间
        expires_at = None
        for access in valid_accesses:
            if access.expires_at:
                if not expires_at or access.expires_at > expires_at:
                    expires_at = access.expires_at
        
        return {
            "success": True,
            "data": {
                "has_access": True,
                "can_export": can_export,
                "expires_at": expires_at.isoformat() if expires_at else None,
                "roles": role_ids
            }
        }
    
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"检查数据集访问权限失败: {str(e)}"
        ) 